// Rong Xue DA8
// I2C sine wave Generator
///////////////////////////////////////////////////////

#include <avr/io.h>
#include<stdio.h>
#include <avr/interrupt.h>
#define F_CPU 8000000UL


#define W_ADD 0xC0 //write to address


void FreqConver(uint16_t freqC)
// function convert the control value get from ADC to the sine wave value
{
	TWSR &= ~((1<<TWPS0) | (1<<TWPS1)); //set prescaler = 1
	TWBR = (F_CPU / 1000UL / freqC - 16) / 2; // / 1; //(prescaler = 1)
}

void i2c_init(void)
// Initialize the sine wave
{
	FreqConver(50);// Set the initial frequency = 50 KHz
	TWCR = 1<<PB4; //enable TWI module
}

void stopi2c()
// function stop the i2c. TWINT = TWI interrupt,TWEN = TWI enable, TWSTO = TWI STOP condition
{
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}


void writei2c(unsigned char data)
// function store data in to the TWI register
{
	TWDR = data;
	TWCR = (1<<TWINT)|(1<<TWEN);
}


void starti2c(void)
// function start the i2c
{
	TWCR = (1<< TWINT) | (1<<TWSTA) | (1<< TWEN);
}


int main(void)
{
	int pos = 0; //declaration of look up table position, initial position is 0
	uint16_t tmpV = 0; //declaration of frequency value, the initial value is 0
	DDRB = ~1<<PB4; // set PB 4 as output
	DDRC = 0x00; //set PC0 as input for ADC input
	OCR1AH = 0x1F;
	OCR1AL = 0x40;
	TCCR1A = 0x00; //CTC, TOP = 0CR1A
	TCCR1B = 0x09; //set prescaler = 1
	TIMSK1 = (1<<OCIE1A);
	ADCSRA =0x8f; // prescaler=128
	ADMUX =0xc0;
	
	int sine_table[128] = { // sine lookup table
		0xccd,0xd6d,0xe0e,0xead,0xf4c,0xfe9,0x1084,0x111c,
		0x11b2,0x1245,0x12d5,0x1361,0x13e9,0x146c,0x14eb,0x1565,
		0x15d9,0x1648,0x16b1,0x1714,0x1771,0x17c7,0x1816,0x185e,
		0x18a0,0x18d9,0x190c,0x1937,0x195a,0x1976,0x1989,0x1995,
		0x1999,0x1995,0x1989,0x1976,0x195a,0x1937,0x190c,0x18d9,
		0x18a0,0x185e,0x1816,0x17c7,0x1771,0x1714,0x16b1,0x1648,
		0x15d9,0x1565,0x14eb,0x146c,0x13e9,0x1361,0x12d5,0x1245,
		0x11b2,0x111c,0x1084,0xfe9,0xf4c,0xead,0xe0e,0xd6d,
		0xccd,0xc2c,0xb8b,0xaec,0xa4d,0x9b0,0x915,0x87d,
		0x7e7,0x754,0x6c4,0x638,0x5b0,0x52d,0x4ae,0x434,
		0x3c0,0x351,0x2e8,0x285,0x228,0x1d2,0x183,0x13b,
		0xf9,0xc0,0x8d,0x62,0x3f,0x23,0x10,0x4,
		0x0,0x4,0x10,0x23,0x3f,0x62,0x8d,0xc0,
		0xf9,0x13b,0x183,0x1d2,0x228,0x285,0x2e8,0x351,
		0x3c0,0x434,0x4ae,0x52d,0x5b0,0x638,0x6c4,0x754,
		0x7e7,0x87d,0x915,0x9b0,0xa4d,0xaec,0xb8b,0xc2c,
	};
	sei();
	
	i2c_init();// Initialization of i2c
	while(1)
	{
		pos = (pos + 1) & (128-1); // new position of the sine wave
		tmpV = sine_table[pos]; // pick the sine value from the sine wave table by the position
		
		char lVout = tmpV;
		char hVout = (tmpV>>8) & 0x0F;
		starti2c(); // Start i2c
		writei2c(W_ADD);
		writei2c(hVout);
		writei2c(lVout);
		stopi2c();
	}
	
	return 0;
}

ISR (TIMER1_COMPA_vect)
{
	ADCSRA |= (1 << ADSC); //ADC start conversion
}

ISR (ADC_vect)
{
	uint16_t freqC; //Frequency of the sine wave
	uint8_t ADC_value_L=ADCL;
	uint16_t ADC_value=(ADCH<<8)|ADC_value_L; //get value from the temp sensor
	
	freqC = ADC_value /55;// ADC Scale is 1024/200=5, minimum frequency is 50. 50+5 =55
	FreqConver(freqC); //set frequency of the sine wave
}
